package com.spzx.product.controller;

import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageHelper;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.core.web.controller.BaseController;
import com.spzx.common.core.web.domain.AjaxResult;
import com.spzx.common.core.web.page.TableDataInfo;
import com.spzx.product.api.dto.ProductSkuVo;
import com.spzx.product.domain.Product;
import com.spzx.product.domain.ProductSku;
import com.spzx.product.query.SkuQuery;
import com.spzx.product.service.*;
import com.spzx.product.vo.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author : 戚欣扬
 * @Description :
 */
@Tag(name = "聚合数据")
@RestController
@RequestMapping("/channel")
@RequiredArgsConstructor
public class ChannelController extends BaseController {
    private final ICategoryService categoryService;
    private final IProductSkuService productSkuService;
    private final IBrandService brandService;
    private final ISkuStockService skuStockService;
    private final IProductDetailsService productDetailsService;
    private final IProductService productService;
    private final RedisTemplate redisTemplate;
    private final ThreadPoolExecutor myThreadPoolExecutor;
    @Operation(summary = "获取首页数据")
    @GetMapping("/index")
    public AjaxResult index(){
        List<CategoryVo> levelOneCategory = categoryService.getLevelOneCategory();
        List<ProductSkuVo> topSale = productSkuService.getTopSale();
        IndexDataVo indexDataVo = new IndexDataVo();
        indexDataVo.setCategoryList(levelOneCategory);
        indexDataVo.setProductSkuList(topSale);
        return AjaxResult.success(indexDataVo);
    }

    @Operation(summary = "获取分类嵌套列表")
    @GetMapping( "/category")
    public AjaxResult category() {
        return AjaxResult.success(categoryService.tree());
    }

    @Operation(summary = "显示商品列表")
    @GetMapping("/skuList/{pageNum}/{pageSize}")
    public TableDataInfo skuList(@PathVariable Integer pageNum, @PathVariable Integer pageSize, SkuQuery skuQuery){
        PageHelper.startPage(pageNum,pageSize);
        List<ProductSkuVo> list = productSkuService.selectProductSkuList(skuQuery);
        return getDataTable(list);
    }

    @Operation(summary = "查询所有品牌")
    @GetMapping("/brand")
    public AjaxResult brandList(){
       return AjaxResult.success(brandService.list());
    }

    @Operation(summary = "商品详情")
    @GetMapping("/item/{skuId}")
    public AjaxResult item(@PathVariable Long skuId){
        //1.布隆过滤器
        Boolean flag = redisTemplate.opsForValue().getBit("product:sku:data", skuId);
        if(!flag){
            throw new ServiceException("访问商品不存在");
        }

        ItemVo itemVo = new ItemVo();
        //base on skuId get spu-sku entity and get productId
        ProductSku productSku = productSkuService.getProductSku(skuId);
        Long productId = productSku.getProductId();
        itemVo.setProductSku(productSku);
        //CompletableFuture异步编排
        //1.async:a:无入参，有返回值
        CompletableFuture<Product> productCompletableFuture = CompletableFuture.supplyAsync(() -> productService.getById(productId), myThreadPoolExecutor);
        //2.async:b:need Param a线程返回值，no return
        CompletableFuture<Void> voidCompletableFuture0 = productCompletableFuture.thenAcceptAsync(product -> {
            itemVo.setSliderUrlList(product.getSliderUrls().split(","));
            itemVo.setSpecValueList(JSON.parseArray(product.getSpecValue()));
        }, myThreadPoolExecutor);
        //3.async:c:alone
        CompletableFuture<SkuPriceVo> skuPriceVoCompletableFuture = CompletableFuture.supplyAsync(() -> productSkuService.getSkuPrice(skuId), myThreadPoolExecutor);
        skuPriceVoCompletableFuture.thenAcceptAsync(itemVo::setSkuPrice,myThreadPoolExecutor);

        CompletableFuture<SkuStockVo> skuStockVoCompletableFuture = CompletableFuture.supplyAsync(() -> skuStockService.getSkuStock(skuId), myThreadPoolExecutor);
        skuStockVoCompletableFuture.thenAcceptAsync(itemVo::setSkuStock,myThreadPoolExecutor);

        CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> {
            itemVo.setDetailsImageUrlList(productDetailsService.getProductDetails(productId));
        }, myThreadPoolExecutor);

        CompletableFuture<Void> voidCompletableFuture2 = CompletableFuture.runAsync(() -> {
            itemVo.setSkuSpecValueMap(productSkuService.getSkuSpecValue(productId));
        }, myThreadPoolExecutor);

        CompletableFuture.allOf(
                skuPriceVoCompletableFuture,
                skuStockVoCompletableFuture,
                voidCompletableFuture0,
                voidCompletableFuture1,
                voidCompletableFuture2
        ).join();
        return AjaxResult.success(itemVo);
    }
}


